介绍


1. redis 主从复制的问题

  • Redis主从复制可将主节点数据同步给从节点,从节点此时有两个作用:

    • 一旦主节点宕机,从节点作为主节点的备份可以随时顶上来

    • 扩展主节点的读能力,分担主节点读压力

  • 但是问题是:

    • 一旦主节点宕机,从节点上位,那么需要人为修改所有应用方的主节点地址(改为新的master地址),还需要命令所有从节点复制新的主节点

  • 那么这个问题,redis-sentinel就可以解决了

2. redis-sentinel 的介绍

  • redis-sentinel 是 redis 官方推荐的高可用性解决方案

  • 当用 redis 作 master(主)-slave(从) 的主从复制的时候,如果 master(主) 本身宕机,redis本身或者客户端都没有实现主从切换的功能

  • 而 redis-sentinel 就是一个独立运行的进程,用于监控多个 master(主)-slave(从) 集群,自动发现 master(主) 宕机,进行自动切换将某一个 slave(从) 设置为 master(主)

  • redis-sentinel只是redis的一个进程,它不存储数据,只用于监控 redis 的状态

  • redis-sentinel 可以创建多个 sentinel(哨兵) 进行监控

  • redis-sentinel 的默认端: 26379

3. sentinel(哨兵) 的主要功能

  • 监控 redis 是否良好运行,每个一秒中向 master(主)节点 或 slave(从)节点 发送一个ping的命令查看这些节点是否能ping通

  • 如果发现 master(主)节点 ping 不通,那么 sentinel(哨兵) 就会和其他 sentinel(哨兵) 进行 “协商” 选择某一个 slave(从)节点 作为 master(主)节点

  • 当 sentinel(哨兵) 进行过主从切换后,主redis配置文件、从redis配置文件、sentinel(哨兵)配置文件 都会发生变化,即: 原本的 主redis配置文件 中会多一行 slaveof 配置项,sentinel(哨兵)配置文件的监控目标也随之改变

4. sentinel(哨兵) 是如何发现其他 sentinel(哨兵) 的

  • sentinel 会通过命令连接向被监视的主从服务器发送 "Hello" 信息,该信息包含了 sentinel 的 ip、端口、id 等内容,以此来向其他 sentinel 宣告自己的存在。与此同时 sentinel 会通过订阅连接接收其他 sentinel 的 "Hello" 信息,以此来发现监视同一个主服务器的其他 sentinel


  • sentinel 通过发送 "Hello" 信息来让 sentinel2 和 sentinel3 发现自己,其他两个 sentinel 也会进行类似的操作

5. redis-sentinel 的架构图






环境的准备


  • 配置主从复制 -> 一主两从

1. 创建 redis-sentinel 文件夹

  • 创建文件夹 /opt/redis-4.0.10/my_redis_sentinel -> 用于存放 sentinel(哨兵)配置 和 redis 配置文件,方便管理

mkdir /opt/redis-4.0.10/my_redis_sentinel

2. 配置主redis(master) 

  • 创建 主redis 配置文件 -> redis-6380.conf

touch /opt/redis-4.0.10/my_redis_sentinel/redis-6380.conf

  • 修改 主redis 配置文件 -> redis-6380.conf

    • 进入配置文件

vim /opt/redis-4.0.10/my_redis_sentinel/redis-6380.conf

    • 修改配置文件

# 绑定远程连接ip,如需要远程访问当前服务器的redis(即: 让别人连接你的redis),那么就需要填写当前服务器的ip -> 0.0.0.0 代表 127.0.0.1 也代表 当前服务器ip
bind 0.0.0.0

# redis 端口
port 6380

# 是否后台运行 redis,在执行 redis-server redis.conf 命令时,如果为 yes 那么就不进入阻塞状态(即: 还可以输入其他命令),如果为 no 进入阻塞状态 (即: 无法输入别的命令)
daemonize yes

# 日志文件,注意: /data/6380/ 目录必须存在(即: 如果没有就需要手动创建)
logfile "/data/6380/redis.log"

# 配置 redis 的数据存放文件夹,一般存放redis的持久化存储文件和redis的日志文件等,注意: /data/6380/ 目录必须存在(即: 如果没有就需要手动创建)
dir /data/6380

# 定义 RDB 持久化文件名
dbfilename dump-6380.rdb

  • 创建reids配置文件所需要的文件夹

mkdir /data/6380

3. 配置从redis1(slave1)

  • 创建 从redis 配置文件 -> redis-6381.conf

touch /opt/redis-4.0.10/my_redis_sentinel/redis-6381.conf

  • 修改 从redis 配置文件 -> redis-6381.conf

    • 进入配置文件

vim /opt/redis-4.0.10/my_redis_sentinel/redis-6381.conf

    • 修改配置文件

# 绑定远程连接ip,如需要远程访问当前服务器的redis(即: 让别人连接你的redis),那么就需要填写当前服务器的ip -> 0.0.0.0 代表 127.0.0.1 也代表 当前服务器ip
bind 0.0.0.0

# redis 端口
port 6381

# 是否后台运行 redis,在执行 redis-server redis.conf 命令时,如果为 yes 那么就不进入阻塞状态(即: 还可以输入其他命令),如果为 no 进入阻塞状态 (即: 无法输入别的命令)
daemonize yes

# 日志文件,注意: /data/6381/ 目录必须存在(即: 如果没有就需要手动创建)
logfile "/data/6381/redis.log"

# 配置 redis 的数据存放文件夹,一般存放redis的持久化存储文件和redis的日志文件等,注意: /data/6381/ 目录必须存在(即: 如果没有就需要手动创建)
dir /data/6381

# 定义 RDB 持久化文件名
dbfilename dump-6381.rdb

# 将 6380 redis 设置为当前的 6381 redis 的 主redis
slaveof 127.0.0.1 6380

  • 创建reids配置文件所需要的文件夹

mkdir /data/6381

3. 配置从redis2(slave2)

  • 创建 从redis 配置文件 -> redis-6382.conf

touch /opt/redis-4.0.10/my_redis_sentinel/redis-6382.conf

  • 修改 从redis 配置文件 -> redis-6382.conf

    • 进入配置文件

vim /opt/redis-4.0.10/my_redis_sentinel/redis-6382.conf

    • 修改配置文件

# 绑定远程连接ip,如需要远程访问当前服务器的redis(即: 让别人连接你的redis),那么就需要填写当前服务器的ip -> 0.0.0.0 代表 127.0.0.1 也代表 当前服务器ip
bind 0.0.0.0

# redis 端口
port 6382

# 是否后台运行 redis,在执行 redis-server redis.conf 命令时,如果为 yes 那么就不进入阻塞状态(即: 还可以输入其他命令),如果为 no 进入阻塞状态 (即: 无法输入别的命令)
daemonize yes

# 日志文件,注意: /data/6382/ 目录必须存在(即: 如果没有就需要手动创建)
logfile "/data/6382/redis.log"

# 配置 redis 的数据存放文件夹,一般存放redis的持久化存储文件和redis的日志文件等,注意: /data/6382/ 目录必须存在(即: 如果没有就需要手动创建)
dir /data/6382

# 定义 RDB 持久化文件名
dbfilename dump-6382.rdb

# 将 6380 redis 设置为当前的 6382 redis 的 主redis
slaveof 127.0.0.1 6380

  • 创建reids配置文件所需要的文件夹

mkdir /data/6382

4. 启动所有redis

redis-server /opt/redis-4.0.10/my_redis_sentinel/redis-6380.conf

redis-server /opt/redis-4.0.10/my_redis_sentinel/redis-6381.conf

redis-server /opt/redis-4.0.10/my_redis_sentinel/redis-6382.conf

5. 查看 redis 是否启动

ps -ef | grep redis


6. 查看 redis 是否能 ping 通

[root@kevin_linux /data 07:43:04]# redis-cli -h 10.0.0.3 -p 6380
10.0.0.3:6380> ping
PONG

[root@kevin_linux /data 07:43:39]# redis-cli -h 10.0.0.3 -p 6381
10.0.0.3:6381> ping
PONG

[root@kevin_linux /data 07:43:56]# redis-cli -h 10.0.0.3 -p 6382
10.0.0.3:6382> ping
PONG

7. 查看 redis 的主从身份状态

redis-cli -p 6380 info replication


redis-cli -p 6381 info replication


redis-cli -p 6382 info replication


7. 在 主redis(master) 写入数据,在 从redis(slave) 查看数据


redis-sentinel 的配置


  • 注意: 

    • redis-sentinel只是redis的一个进程,它不存储数据,只用于监控 redis 的状态

    • sentinel 默认端口号 26379

    • 可以创建多个 sentinel(哨兵) 进行监控

1. 创建 sentinel 配置文件

  • 创建三个 sentinel 配置文件到 /opt/redis-4.0.10/my_redis_sentinel 目录下

touch /opt/redis-4.0.10/my_redis_sentinel/sentinel-26380.conf

touch /opt/redis-4.0.10/my_redis_sentinel/sentinel-26381.conf

touch /opt/redis-4.0.10/my_redis_sentinel/sentinel-26382.conf

2. 配置 sentinel-26380.conf 配置文件

  • 进入配置文件

vim /opt/redis-4.0.10/my_redis_sentinel/sentinel-26380.conf

  • 修改配置文件

# sentinel 端口
port 26380

# 是否后台运行 sentinel,在执行 redis-server redis.conf 命令时,如果为 yes 那么就不进入阻塞状态(即: 还可以输入其他命令),如果为 no 进入阻塞状态 (即: 无法输入别的命令)
daemonize yes

# 日志文件,注意: /data/26380/ 目录必须存在(即: 如果没有就需要手动创建)
logfile "/data/26380/sentinel.log"

# 配置 sentinel 的数据存放文件夹,注意: /data/26380/ 目录必须存在(即: 如果没有就需要手动创建)
dir /data/26380

# 让当前 sentinel 节点监控 10.0.0.3:6380 这个主节点(即:主redis)
# mymaster : 是主节点的别名,可以起别的名字
# 2 : 代表判断主节点(即:主redis)失败(即:宕机)至少需要2个sentinel节点节点同意
sentinel monitor mymaster 10.0.0.3 6380 2

# 当 sentinel 节点集合对主节点(即:主redis)故障判定达成一致时,sentinel领导者节点会做故障转移操作,选出新的主节点(即:主redis),原来的从节点(即:从redis)会向新的主节点(即:主redis)发起复制操作,限制每次向新的主节点(即:主redis)发起复制操作的从节点(即:从redis)个数为1
sentinel parallel-syncs mymaster 1

# 故障转移超时时间为 180000 毫秒
sentinel failover-timeout mymaster 180000

  • 创建sentinel配置文件所需要的文件夹

mkdir /data/26380

3. 配置 sentinel-26381.conf 配置文件

  • 进入配置文件

vim /opt/redis-4.0.10/my_redis_sentinel/sentinel-26381.conf

  • 修改配置文件

# sentinel 端口
port 26381

# 是否后台运行 sentinel,在执行 redis-server redis.conf 命令时,如果为 yes 那么就不进入阻塞状态(即: 还可以输入其他命令),如果为 no 进入阻塞状态 (即: 无法输入别的命令)
daemonize yes

# 日志文件,注意: /data/26381/ 目录必须存在(即: 如果没有就需要手动创建)
logfile "/data/26381/sentinel.log"

# 配置 sentinel 的数据存放文件夹,注意: /data/26381/ 目录必须存在(即: 如果没有就需要手动创建)
dir /data/26381

# 让当前 sentinel 节点监控 10.0.0.3:6380 这个主节点(即:主redis)
# mymaster : 是主节点的别名,可以起别的名字
# 2 : 代表判断主节点(即:主redis)失败(即:宕机)至少需要2个sentinel节点节点同意
sentinel monitor mymaster 10.0.0.3 6380 2

# 当 sentinel 节点集合对主节点(即:主redis)故障判定达成一致时,sentinel领导者节点会做故障转移操作,选出新的主节点(即:主redis),原来的从节点(即:从redis)会向新的主节点(即:主redis)发起复制操作,限制每次向新的主节点(即:主redis)发起复制操作的从节点(即:从redis)个数为1
sentinel parallel-syncs mymaster 1

# 故障转移超时时间为 180000 毫秒
sentinel failover-timeout mymaster 180000

  • 创建sentinel配置文件所需要的文件夹

mkdir /data/26381

4. 配置 sentinel-26382.conf 配置文件

  • 进入配置文件

vim /opt/redis-4.0.10/my_redis_sentinel/sentinel-26382.conf

  • 修改配置文件

# sentinel 端口
port 26382

# 是否后台运行 sentinel,在执行 redis-server redis.conf 命令时,如果为 yes 那么就不进入阻塞状态(即: 还可以输入其他命令),如果为 no 进入阻塞状态 (即: 无法输入别的命令)
daemonize yes

# 日志文件,注意: /data/26382/ 目录必须存在(即: 如果没有就需要手动创建)
logfile "/data/26382/sentinel.log"

# 配置 sentinel 的数据存放文件夹,注意: /data/26382/ 目录必须存在(即: 如果没有就需要手动创建)
dir /data/26382

# 让当前 sentinel 节点监控 10.0.0.3:6380 这个主节点(即:主redis)
# mymaster : 是主节点的别名,可以起别的名字
# 2 : 代表判断主节点(即:主redis)失败(即:宕机)至少需要2个sentinel节点节点同意
sentinel monitor mymaster 10.0.0.3 6380 2

# 当 sentinel 节点集合对主节点(即:主redis)故障判定达成一致时,sentinel领导者节点会做故障转移操作,选出新的主节点(即:主redis),原来的从节点(即:从redis)会向新的主节点(即:主redis)发起复制操作,限制每次向新的主节点(即:主redis)发起复制操作的从节点(即:从redis)个数为1
sentinel parallel-syncs mymaster 1

# 故障转移超时时间为 180000 毫秒
sentinel failover-timeout mymaster 180000

  • 创建sentinel配置文件所需要的文件夹

mkdir /data/26382

5. 启动 sentinel(哨兵)

redis-sentinel /opt/redis-4.0.10/my_redis_sentinel/sentinel-26380.conf

redis-sentinel /opt/redis-4.0.10/my_redis_sentinel/sentinel-26381.conf

redis-sentinel /opt/redis-4.0.10/my_redis_sentinel/sentinel-26382.conf

6. 查看sentinel(哨兵)是否启动

ps -ef | grep redis


6. 查看sentinel(哨兵)的状态

redis-cli -p 26380 info sentinel


redis-cli -p 26381 info sentinel


redis-cli -p 26382 info sentinel


redis 故障实验


1. 大致思路

  • 结束 主redis进程6380端口,观察从redis是否会进行新的主redis(master)选举,进行切换

  • 重新启动旧的 主redis,查看此时 redis 的状态身份

2. 结束主redis进程6380端口

ps -ef | grep redis

kill -9 7411


3. 等待 sentinel 进行主从切换(即: 30秒后查看从redis的身份状态

4. 查看从redis的身份状态

  • 此时查看所有从redis的身份状态,查看是否有一个从reids被设置为了主redis

    • 此时 从redis 6381 被设置为了 主redis

redis-cli -p 6381 info replication


    • 此时 从redis 6382 的所设置的主redis被给改为 redis 6381

redis-cli -p 6382 info replication


4. 重新启动旧的 主redis,查看此时 redis 的状态身份

  • 重新启动旧的 主redis

redis-server /opt/redis-4.0.10/my_redis_sentinel/redis-6380.conf

  • 查看此时旧的 主redis 的状态身份

redis-cli -p 6380 info replication


5. 查看此时新主 redis 的状态身份

redis-cli -p 6381 info replication


6. 查 redis 配置文件 和 sentinel 配置文件的变化

  • 注意: 当 sentinel 配置文件变化后,原本的注释已经对应不上他的配置项了,所以不要去查看这些注释

  • 查 redis 配置文件的变化

vim /opt/redis-4.0.10/my_redis_sentinel/redis-6380.conf


vim /opt/redis-4.0.10/my_redis_sentinel/redis-6381.conf


vim /opt/redis-4.0.10/my_redis_sentinel/redis-6382.conf


  • 查 sentinel 配置文件的变化

vim /opt/redis-4.0.10/my_redis_sentinel/sentinel-26380.conf


vim /opt/redis-4.0.10/my_redis_sentinel/sentinel-26381.conf


vim /opt/redis-4.0.10/my_redis_sentinel/sentinel-26382.conf